import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mticker

plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置字体为黑体
plt.rcParams['axes.unicode_minus'] = False  # 显示负号  

file1 = '某购物中心三年销售数据.xlsx'
df = pd.read_excel(file1, sheet_name='每日商场汇总', header=0)

##
# 取前30天数据
n = 30
dates = df['日期'].head(n)
dates = pd.to_datetime(dates).dt.strftime('%Y-%m-%d')  # 去掉00:00:00
sales = df['销售额'].head(n) / 100  # 销售额以100为单位
traffic = df['客流量'].head(n)

x = np.arange(n)
width = 0.35

plt.figure(figsize=(14, 6))
plt.bar(x - width/2, sales, width=width, label='销售额', color="#eb665f", edgecolor='k')
plt.bar(x + width/2, traffic, width=width, label='客流量', color='#00bfc4', edgecolor='k')

plt.xlabel('日期', fontsize=11)
plt.ylabel('数值（销售额：百元，客流量：人）', fontsize=11)
plt.title('前30天总销售额与客流量分组柱状图')
plt.xticks(x, dates, rotation=45, ha='right', fontsize=9)
plt.legend()
plt.tight_layout()
plt.savefig('前30天总销售额与客流量分组柱状图.png')
plt.show()

##
# 按月份统计累计销售额和累计客流量
df['月份'] = pd.to_datetime(df['日期']).dt.strftime('%Y-%m')
monthly_sales = df.groupby('月份')['销售额'].sum() / 100  # 以百元为单位
monthly_traffic = df.groupby('月份')['客流量'].sum()

months = monthly_sales.index.tolist()
x = np.arange(len(months))
width = 0.35

plt.figure(figsize=(12, 6))
plt.bar(x - width/2, monthly_sales, width=width, label='月累计销售额', color='#f9766e', edgecolor='k')
plt.bar(x + width/2, monthly_traffic, width=width, label='月累计客流量', color='#00bfc4', edgecolor='k')

plt.xlabel('月份', fontsize=11)
plt.ylabel('累计数值（销售额：百元，客流量：人）', fontsize=11)
plt.title('每月累计销售额与累计客流量分组柱状图')
plt.xticks(x, months, rotation=45, ha='right', fontsize=10)

# 设置纵坐标为科学计数法
plt.gca().yaxis.set_major_formatter(mticker.ScalarFormatter(useMathText=True))
plt.ticklabel_format(style='sci', axis='y', scilimits=(0,0))

plt.legend()
plt.tight_layout()
plt.savefig('每月累计销售额与累计客流量分组柱状图.png')
plt.show()

##
# 合并每个月份累计销售额和累计客流量的面积折线图（累计销售额为鲜红色，累计客流量为鲜绿色）
monthly_df = pd.DataFrame({
    '累计销售额（百元）': monthly_sales,
    '累计客流量（人）': monthly_traffic
}, index=months)

plt.figure(figsize=(12, 6))
ax = monthly_df.plot.area(
    ax=plt.gca(),
    alpha=0.3,
    color=['#FF3030', '#00FF7F'],  # 鲜红色和鲜绿色
    linewidth=0,
    stacked=False
)
monthly_df.plot(
    ax=ax,
    color=['#FF3030', '#00FF7F'],  # 鲜红色和鲜绿色
    linewidth=2
)
plt.xlabel('月份', fontsize=11)
plt.ylabel('累计数值（销售额：百元，客流量：人）', fontsize=11)
plt.title('每月累计销售额与累计客流量面积折线图')
plt.xticks(rotation=45, ha='right', fontsize=10)
# 设置纵坐标为科学计数法
ax.yaxis.set_major_formatter(mticker.ScalarFormatter(useMathText=True))
ax.ticklabel_format(style='sci', axis='y', scilimits=(0,0))
# 只保留一个累计销售额和一个累计客流量的标签
handles, labels = ax.get_legend_handles_labels()
unique_labels = []
unique_handles = []
for h, l in zip(handles, labels):
    if l not in unique_labels:
        unique_labels.append(l)
        unique_handles.append(h)
ax.legend(unique_handles, unique_labels)
plt.tight_layout()
plt.savefig('每月累计销售额与累计客流量面积折线图.png')
plt.show()

##
# 读取商铺明细数据
file2 = '某购物中心三年销售数据.xlsx'
df2 = pd.read_excel(file2, sheet_name='某商场月度商铺明细', header=0)

# 提取年份
df2['年份'] = pd.to_datetime(df2['月份']).dt.year
df2 = df2[(df2['年份'] >= 2014) & (df2['年份'] <= 2016)]

# 找出每年每层销售额最大的商铺及其销售额
idx = df2.groupby(['年份', '层数'])['销售额'].idxmax() 

max_sales_shops = df2.loc[idx, ['年份', '层数', '商铺名称', '销售额']]

# 生成透视表：行是年份，列是层数，值是最大销售额和商铺名称
pivot_sales = max_sales_shops.pivot(index='年份', columns='层数', values='销售额')  # 销售额以百元为单位
pivot_names = max_sales_shops.pivot(index='年份', columns='层数', values='商铺名称')
pivot_sales = pivot_sales / 10000
# 绘制分组柱状图
years = pivot_sales.index.tolist()
floors = pivot_sales.columns.tolist()
x = np.arange(len(years))
width = 0.8 / len(floors)

plt.figure(figsize=(10, 6))

# 对层数排序，负一层最左，负一夹层第二
def floor_sort_key(floor):
    if '负一夹层' in str(floor):
        return -0.5
    elif '负一' in str(floor):
        return -1
    else:
        try:
            return float(floor)
        except:
            return 100

floors_sorted = sorted(floors, key=floor_sort_key)

for i, floor in enumerate(floors_sorted):
    plt.bar(x + i*width, pivot_sales[floor], width=width, label=f'{floor}')
    # 在柱子上标注商铺名称，字体加粗加大
    for xi, yi, name in zip(x + i*width, pivot_sales[floor], pivot_names[floor]):
        plt.text(
            xi, yi, str(name),
            ha='center', va='bottom',
            fontsize=10, fontweight='bold'
        )

plt.xlabel('年份')
plt.ylabel('销售额（万元）')
plt.title('2014-2016每年每层销售额最大的商铺及其销售额')
plt.xticks(x + width*(len(floors_sorted)-1)/2, years)



# 在每组柱状图底下标注层数
for i, floor in enumerate(floors_sorted):
    for xi in x + i*width:
        plt.text(
            xi, 0, f'{floor}',
            ha='center', va='top',
            fontsize=10, color='black', rotation=0, fontweight='bold'
        )

plt.legend(title='层数')
plt.tight_layout()
plt.savefig('2014-2016每年每层销售额最大的商铺及其销售额.png')
plt.show()


##
# 统计2014、2015、2016年租售比区间分布并绘制扇形图
# 假设df2中有“年份”和“租售比”两列，租售比为百分数（如15表示15%）
df2['年份'] = pd.to_datetime(df2['月份']).dt.year
df2 = df2[(df2['年份'] >= 2014) & (df2['年份'] <= 2016)]

for year in [2014, 2015, 2016]:
    data = df2[df2['年份'] == year]
    bins = [0, 10, 15, 20, 1000]
    labels = ['<10%', '10%-15%', '15%-20%', '>20%']
    rent_sale_group = pd.cut(data['租售比'] * 100, bins=bins, labels=labels, right=False)
    counts = rent_sale_group.value_counts().reindex(labels, fill_value=0)
    plt.figure(figsize=(7, 7))
    wedges, texts, autotexts = plt.pie(
        counts,
        labels=labels,
        autopct='%1.1f%%',
        colors=['#8fd9b6', "#f4be41", '#f67280', '#ADD8E6'],
        startangle=90,
        counterclock=False
    )
    # 设置百分比数字和标签字体加大
    for autotext in autotexts:
        autotext.set_fontsize(16)
        autotext.set_fontweight('bold')
    for text in texts:
        text.set_fontsize(16)
        text.set_fontweight('bold')
    plt.title(f'{year}年租售比区间分布', fontsize=18)
    plt.tight_layout()
    plt.savefig(f'{year}年租售比区间分布饼图.png')
    plt.show()

##
# 计算每月份的平均销售坪效和平均租金，并绘制面积折线图（去除0值）

df2['月份'] = pd.to_datetime(df2['月份'])
df2 = df2[(df2['月份'] >= '2014-01-01') & (df2['月份'] <= '2016-12-31')]
df2['月份_str'] = df2['月份'].dt.strftime('%Y-%m')

# 去除销售坪效和平均租金为0的数据
df2_filtered = df2[(df2['销售坪效'] != 0) & (df2['平均租金'] != 0)]

monthly_avg = df2_filtered.groupby('月份_str')[['销售坪效', '平均租金']].mean()

plt.figure(figsize=(14, 6))
ax = monthly_avg.plot.area(
    ax=plt.gca(),
    alpha=0.3,
    color=['#f9766e', '#00bfc4'],
    linewidth=0,
    stacked=False
)
monthly_avg.plot(
    ax=ax,
    color=['#f9766e', '#00bfc4'],
    linewidth=2
)
plt.xlabel('月份', fontsize=11)
plt.ylabel('平均值', fontsize=11)
plt.title('每月平均销售坪效与平均租金面积折线图')
plt.xticks(rotation=0, ha='right', fontsize=11)

# 只保留一个累计销售坪效和一个平均租金的标签
handles, labels = ax.get_legend_handles_labels()
unique_labels = []
unique_handles = []
for h, l in zip(handles, labels):
    if l not in unique_labels:
        unique_labels.append(l)
        unique_handles.append(h)
ax.legend(unique_handles, unique_labels)
plt.tight_layout()
plt.savefig('每月平均销售坪效与平均租金面积折线图.png')
plt.show()

##
# 计算每月份每层的平均销售坪效，并绘制折线图（去除0值）

df2['月份'] = pd.to_datetime(df2['月份'])
df2 = df2[(df2['月份'] >= '2014-01-01') & (df2['月份'] <= '2016-12-31')]
df2['月份_str'] = df2['月份'].dt.strftime('%Y-%m')

# 去除销售坪效为0的数据
df2_filtered = df2[df2['销售坪效'] != 0]

# 按月份和层数分组，计算平均销售坪效
monthly_floor_avg = df2_filtered.groupby(['月份_str', '层数'])['销售坪效'].mean().unstack()

plt.figure(figsize=(16, 7))
ax = monthly_floor_avg.plot(
    ax=plt.gca(),
    linewidth=2,
    marker='o'
)
plt.xlabel('月份', fontsize=12)
plt.ylabel('平均销售坪效', fontsize=12)
plt.title('每月每层平均销售坪效折线图')
plt.xticks(rotation=45, ha='right', fontsize=11)
handles, labels = ax.get_legend_handles_labels()
unique_labels = []
unique_handles = []
for h, l in zip(handles, labels):
    if l not in unique_labels:
        unique_labels.append(l)
        unique_handles.append(h)
ax.legend(unique_handles, unique_labels)
plt.tight_layout()
plt.savefig('每月每层平均销售坪效折线图.png')
plt.show()


##
# 绘制2014、2015、2016年各一级业态占比的扇形图
df2['年份'] = pd.to_datetime(df2['月份']).dt.year
df2 = df2[(df2['年份'] >= 2014) & (df2['年份'] <= 2016)]

year = df2['年份'].unique()
for year in [2014, 2015, 2016]:
    data = df2[df2['年份'] == year]
    counts = data['一级业态'].value_counts()
    plt.figure(figsize=(7, 7))
    wedges, texts, autotexts = plt.pie(
        counts,
        labels=counts.index,
        autopct='%1.1f%%',
        startangle=90,
        counterclock=False
    )
    # 设置百分比数字字体加大
    for autotext in autotexts:
        autotext.set_fontsize(10)
        autotext.set_fontweight('bold')
    plt.title(f'{year}年各一级业态占比')
    plt.tight_layout()
    plt.savefig(f'{year}年一级业态占比饼图.png')
    plt.show()


# 绘制2014、2015、2016年一级业态为餐饮的各二级业态占比的扇形图
df2['年份'] = pd.to_datetime(df2['月份']).dt.year
df2 = df2[(df2['年份'] >= 2014) & (df2['年份'] <= 2016)]

year = df2['年份'].unique()
for year in [2014, 2015, 2016]:
    data = df2[(df2['年份'] == year) & (df2['一级业态'] == '餐饮')]
    counts = data['二级业态'].value_counts()
    plt.figure(figsize=(7, 7))
    wedges, texts, autotexts = plt.pie(
        counts,
        labels=counts.index,
        autopct='%1.1f%%',
        startangle=90,
        counterclock=False
    )
    # 设置百分比数字和标签字体加大
    for autotext in autotexts:
        autotext.set_fontsize(17)
        autotext.set_fontweight('bold')
    for text in texts:
        text.set_fontsize(16)
        text.set_fontweight('bold')
    plt.title(f'{year}年餐饮二级业态占比', fontsize=18)
    plt.tight_layout()
    plt.savefig(f'{year}年餐饮二级业态占比饼图.png')
    plt.show()


# 统计2014-2016年每月一级业态为餐饮的各二级业态占比，并绘制分组面积折线图

df2['月份'] = pd.to_datetime(df2['月份'])
df2 = df2[(df2['月份'] >= '2014-01-01') & (df2['月份'] <= '2016-12-31')]
df2['月份_str'] = df2['月份'].dt.strftime('%Y-%m')

# 只保留一级业态为餐饮的数据
df2_cy = df2[df2['一级业态'] == '餐饮']

# 统计每月各二级业态数量
pivot = df2_cy.pivot_table(index='月份_str', columns='二级业态', values='商铺名称', aggfunc='count', fill_value=0)

# 计算每月各二级业态占比
pivot_pct = pivot.div(pivot.sum(axis=1), axis=0)

plt.figure(figsize=(18, 8))
ax = pivot_pct.plot.area(
    ax=plt.gca(),
    alpha=0.4,
    linewidth=0,
    stacked=False
)
pivot_pct.plot(
    ax=ax,
    linewidth=2
)
plt.xlabel('月份', fontsize=12)
plt.ylabel('占比', fontsize=12)
plt.title('2014-2016年每月餐饮各二级业态占比分组面积折线图')
plt.xticks(rotation=45, ha='right', fontsize=11)

# 设置纵坐标为百分数
ax.yaxis.set_major_formatter(mticker.PercentFormatter(xmax=1, decimals=0))

handles, labels = ax.get_legend_handles_labels()
unique_labels = []
unique_handles = []
for h, l in zip(handles, labels):
    if l not in unique_labels:
        unique_labels.append(l)
        unique_handles.append(h)
ax.legend(unique_handles, unique_labels)
plt.tight_layout()
plt.savefig('2014-2016年每月餐饮各二级业态占比的分组面积折线图.png')
plt.show()


# 计算每月份一级业态为普通服饰的各二级业态占比，并绘制折线图

df2['月份'] = pd.to_datetime(df2['月份'])
df2 = df2[(df2['月份'] >= '2014-01-01') & (df2['月份'] <= '2016-12-31')]
df2['月份_str'] = df2['月份'].dt.strftime('%Y-%m')

# 只保留一级业态为普通服饰的数据
df2_fs = df2[df2['一级业态'] == '普通服饰']

# 统计每月各二级业态数量
pivot_fs = df2_fs.pivot_table(index='月份_str', columns='二级业态', values='商铺名称', aggfunc='count', fill_value=0)

# 计算每月各二级业态占比
pivot_fs_pct = pivot_fs.div(pivot_fs.sum(axis=1), axis=0)

plt.figure(figsize=(18, 8))
ax = pivot_fs_pct.plot(
    ax=plt.gca(),
    linewidth=2,
    marker='o'
)
plt.xlabel('月份', fontsize=12)
plt.ylabel('占比', fontsize=12)
plt.title('2014-2016年每月普通服饰各二级业态占比分组折线图')
plt.xticks(rotation=45, ha='right', fontsize=11)

# 设置纵坐标为百分数
ax.yaxis.set_major_formatter(mticker.PercentFormatter(xmax=1, decimals=0))

handles, labels = ax.get_legend_handles_labels()
unique_labels = []
unique_handles = []
for h, l in zip(handles, labels):
    if l not in unique_labels:
        unique_labels.append(l)
        unique_handles.append(h)
ax.legend(unique_handles, unique_labels)
plt.tight_layout()
plt.savefig('2014-2016年每月普通服饰各二级业态占比分组折线图.png')
plt.show()

##
# 计算2014、2015、2016年每层的平均合同时长，并绘制分组柱形图
# 判断并转换日期格式
if not np.issubdtype(df2['合同起始日期'].dtype, np.datetime64):
    df2['合同起始日期'] = pd.to_datetime(df2['合同起始日期'], errors='coerce')
if not np.issubdtype(df2['合同结束日期'].dtype, np.datetime64):
    df2['合同结束日期'] = pd.to_datetime(df2['合同结束日期'], errors='coerce')

# 计算合同时长（天）
df2['合同时长'] = (df2['合同结束日期'] - df2['合同起始日期']).dt.days

# 只保留2014-2016年数据
df2['年份'] = pd.to_datetime(df2['月份']).dt.year
df2 = df2[(df2['年份'] >= 2014) & (df2['年份'] <= 2016)]

# 按年份和层数分组，计算平均合同时长
avg_duration = df2.groupby(['年份', '层数'])['合同时长'].mean().unstack()

# 绘制分组柱形图
years = avg_duration.index.tolist()
floors = avg_duration.columns.tolist()
x = np.arange(len(years))
width = 0.8 / len(floors)

plt.figure(figsize=(10, 6))
for i, floor in enumerate(floors):
    plt.bar(x + i*width, avg_duration[floor], width=width, label=f'{floor}')
    # 在柱子上标注平均天数
    for xi, yi in zip(x + i*width, avg_duration[floor]):
        plt.text(xi, yi, f'{yi:.0f}', ha='center', va='bottom', fontsize=10, fontweight='bold')

plt.xlabel('年份')
plt.ylabel('平均合同时长（天）')
plt.title('2014-2016年每层平均合同时长')
plt.xticks(x + width*(len(floors)-1)/2, years)
plt.legend(title='层数')
plt.tight_layout()
plt.savefig('2014-2016年每层平均签约合同时长分组柱形图.png')
plt.show()

